package sketch.generator;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import randoop.StatementKind;
import sketch.BatchExecution;
import sketch.ClassCollections;
import sketch.ExecutableSequenceContent;
import sketch.SketchSequence;
import sketch.skeleton.SkeletonCreator;
import sketch.util.Checker;

public class GenTests<T extends SketchSequence> {
	
	/**
	 * A collection of classes under test
	 * */
	static ClassCollections collections  = new ClassCollections();
	
	public final UnitTestGenerator<T> unitTestGenerators;
	
	/**
	 * is there any changes to the generator list
	 * */
	private boolean _generators_changed = false;
	
	public GenTests(String filePath) {
		this._generators_changed = false;
		//SkeletonCreator creator = new SkeletonCreator(filePath);
		this.unitTestGenerators = new UnitTestGenerator<T>(/*creator.createSkeleton()*/);
	}
	
	public boolean hasGeneratorChanged() {
		return this._generators_changed;
	}
	
	public List<ExecutableSequenceContent[]> currentExecutableContents() {
		return unitTestGenerators.getExecutableContentList();
	}
	
	public List<BatchExecution> currentExecutionResults() {
		return unitTestGenerators.getExecutionResults();
	}
	
	public boolean hasNextTest() {
			return unitTestGenerators.hasNext();
	}

	public SketchSequence nextTest() {
		return unitTestGenerators.next();
	}
	
	public SketchSequence currentTest() {
		return unitTestGenerators.current();
	}
	
	public int numOfGenerators() {
		return this.unitTestGenerators.seqgenerators.size();
	}
	
	public Class<?>[] getGeneratorTypes() {
		Class<?>[] types = new Class<?>[this.numOfGenerators()];
		for(int i = 0; i < types.length; i++) {
			types[i] = this.unitTestGenerators.seqgenerators.get(i).getClass();
		}
		return types;
	}
	
	public boolean hasGenerator(SequenceGenerator<T> generator) {
		Checker.checkNull(generator, "The generator input could not be null!");
		return unitTestGenerators.seqgenerators.contains(generator);
	}
	
	public void addGenerators(SequenceGenerator<T>[] generators) {
		Checker.checkNull(generators, "The generator array could not be null!");
		for(SequenceGenerator<T> generator : generators) {
			this.addGenerator(generator);
		}
	}
	
	public void addGenerators(List<SequenceGenerator<T>> generators) {
		Checker.checkNull(generators, "The generator list could not be null!");
		for(SequenceGenerator<T> generator : generators) {
			this.addGenerator(generator);
		}
	}
	
	public void addGenerator(SequenceGenerator<T> generator) {
		Checker.checkNull(generator, "The new added generator could not be null!");
		this.unitTestGenerators.addSequenceGenerator(generator);
		//add a new generator
		this._generators_changed = true;
	}
	
	public static void reset(Class<?> ...classes) {
		Collection<Class<?>> classcollection = new LinkedList<Class<?>>();
		for(Class<?> clazz : classes) {
			classcollection.add(clazz);
			System.out.println("add : " + clazz);
		}
		collections.addToClassesCollection(classcollection);
	}
	
	public static StatementKind lookupForStatement(Class<?> clazz, String methodSignature) {
		return collections.lookforStatement(clazz, methodSignature);
	}
	
	/**
	 * Generating tests
	 * */
	public void genTests() {
		System.out.println("How many generators we have: " + unitTestGenerators.seqgenerators.size());
		for(SequenceGenerator<?> seqGen : unitTestGenerators.seqgenerators) {
			System.out.println("  generator: " + seqGen.getClass());
		}

		Collection<SketchSequence> collection = new LinkedList<SketchSequence>();
		
		int count = 0;
		while(unitTestGenerators.hasNext()) {
			System.out.println((++count) + "th sequence:");
			SketchSequence generated = unitTestGenerators.next();
			//System.out.println(generated.toString());
			System.out.println(JUnitTestCreator.createSingleTest(generated, "testTreeMap" + count));
			System.out.println();
			collection.add(generated);
		}
		JUnitTestCreator.createJUnitTest(collection, ".",  "TreeMapTest", new String[]{});
	}
}
